/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package regulatoryInteractionsStats.yeast;

import functionalEnrichment.semanticSimilarity.semanticSimilarityCalculator.parsers.SimilarityFileParser;
import functionalEnrichment.semanticSimilarity.semanticSimilarityCalculator.units.Gene;
import functionalEnrichment.semanticSimilarity.semanticSimilarityCalculator.units.SemanticSimilarity;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.collections.FastHashMap;
import utils.fishersExact.FishersExactTest;

/**
 *
 * @author jamie
 */
public class SemanticSimStats {

    private File similaritiesFolder = new File("/Users/Shared/yeast3dimension/semanticSimilarity/similarities_sgd/");
    private double prior = 1.0/3.0;
    private YeastGeneLibrary yeastGeneLibrary;
    private RegultoryInteractionSet regultoryInteractionSet;

    public SemanticSimStats() {
        yeastGeneLibrary = new YeastGeneLibrary();
        yeastGeneLibrary.printStats();
        regultoryInteractionSet = new RegultoryInteractionSet(yeastGeneLibrary);
    }

    public TreeMap<Integer, Double> getBayesResults() {
        SimilarityFileParser sfp_bp = getParser("BP");
//        SimilarityFileParser sfp_cc = getParser("CC");
        TreeMap<Integer, Double> bayesResults = new TreeMap<Integer, Double>();
        for (int i = 0; i <= 18; i++) {
            bayesResults.put(i, printDetails(i, regultoryInteractionSet, sfp_bp));
        }
        return bayesResults;
    }

    // argument should equal one of BP, CC or MF
    private File getSimilaritiesFile(String ontology) {
        return new File(similaritiesFolder, "similarities_" + ontology + ".txt");
    }

    private SimilarityFileParser getParser(String ontology) {
        SimilarityFileParser sfp = new SimilarityFileParser();
        try {
            sfp.readAllSimilarities(getSimilaritiesFile(ontology));

        } catch (IOException ex) {
            Logger.getLogger(SemanticSimStats.class.getName()).log(Level.SEVERE, null, ex);
        }
        return sfp;
    }

    private double printDetails(int ssCutoff, RegultoryInteractionSet regultoryInteractionSet, SimilarityFileParser sfp) {

        Map<YeastGene, Gene> annotated = getAnnotatedGenes(regultoryInteractionSet, sfp);
        ProportionStat propReg = getProportion_actual(regultoryInteractionSet, sfp, ssCutoff, annotated);
        ProportionStat propAll = getProportion_all(sfp, ssCutoff, annotated);
        FishersExactTest fet = new FishersExactTest(propAll.getTotal(), propAll.getCount(), propReg.getTotal(), propReg.getCount());
        double pGP = ((propReg.getCount() + 0.0) / propReg.getTotal()) * prior;
        double x = ((propAll.getCount() - propReg.getCount() + 0.0) / (propAll.getTotal()-propReg.getTotal())) * (1 - prior);

        double b = pGP / (pGP + x);
//        System.out.println(ssCutoff + ", noReg: " + propReg.getCount() + ", totalReg: " + propReg.getTotal() + ", propReg: " + propReg.getProp() + ", noAll: " + propAll.getCount() + ", totalAll: " + propAll.getTotal() + ", propAll: " + propAll.getProp() + ", fc: " + 0 + ", fet: " +0  + ", bayes: " + b);
        System.out.println(ssCutoff + ", noReg: " + propReg.getCount() + ", totalReg: " + propReg.getTotal() + ", propReg: " + propReg.getProp() + ", noAll: " + propAll.getCount() + ", totalAll: " + propAll.getTotal() + ", propAll: " + propAll.getProp() + ", fc: " + fet.getFoldChange() + ", fet: " + fet.getResult() + ", bayes: " + b);
        return b;
    }

    private Map<YeastGene, Gene> getAnnotatedGenes(RegultoryInteractionSet regultoryInteractionSet, SimilarityFileParser sfp) {
        Map<YeastGene, Gene> annotated = new TreeMap<YeastGene, Gene>();
        for (String geneSymbol : regultoryInteractionSet.getGenes()) {
            YeastGene yg = regultoryInteractionSet.getYeastGeneLibrary().getGeneBySymbol(geneSymbol);
            if (yg == null) {
                System.out.println(geneSymbol);
            }
            Gene gene = sfp.getGeneLibrary().getGene(yg.getSgdId());
            if (sfp.getAnnotatedGenes().contains(gene)) {
                annotated.put(yg, gene);
            }
        }
        return annotated;
    }

    private ProportionStat getProportion_actual(RegultoryInteractionSet regultoryInteractionSet, SimilarityFileParser sfp, int ssCutoff, Map<YeastGene, Gene> annotated) {
        int total = 0;
        int count = 0;
        ArrayList<YeastGene> yeastGenes = new ArrayList<YeastGene>();
        yeastGenes.addAll(annotated.keySet());
//        System.out.println(yeastGenes.size() + ", " + regultoryInteractionSet.getRegulatoryInteractions().size());
        HashSet<String> keys = new HashSet<String>();
        for (int i = 0; i < yeastGenes.size(); i++) {
            YeastGene gene1 = yeastGenes.get(i);
            Gene g1 = annotated.get(gene1);
            for (int j = i + 1; j < yeastGenes.size(); j++) {
                YeastGene gene2 = yeastGenes.get(j);
                Gene g2 = annotated.get(gene2);
                String symbols[] = {gene1.getSymbol(), gene2.getSymbol()};
                Arrays.sort(symbols);
                String key = symbols[0] + ":" + symbols[1];
                if (!keys.contains(key)) {
                    if (regultoryInteractionSet.getRegulatoryInteractions().contains(key)) {
                        SemanticSimilarity ss = new SemanticSimilarity(g1, g2);
                        if (sfp.getSimilarityHash().containsKey(ss.hashCode())) {
                            int sim = ((SemanticSimilarity) sfp.getSimilarityHash().get(ss.hashCode())).getSimilarity();
                            if (sim >= ssCutoff) {
                                count++;
                            }
                        } else if (ssCutoff == 0) {
                            count++;
                        }
                        total++;
                    } else {
//                        System.out.println("no key: "+key);
                    }
                    keys.add(key);
                } else {
//                    System.out.println("again, key: "+key);
                }
            }
        }

        ProportionStat stat = new ProportionStat(count, total);
        return stat;
    }

    private ProportionStat getProportion_all(SimilarityFileParser sfp, int ssCutoff, Map<YeastGene, Gene> annotated) {
        int total = 0;
        int count = 0;
        ArrayList<YeastGene> yeastGenes = new ArrayList<YeastGene>();
        yeastGenes.addAll(annotated.keySet());
        HashSet<String> keys = new HashSet<String>();
        for (int i = 0; i < yeastGenes.size(); i++) {
            YeastGene gene1 = yeastGenes.get(i);
            Gene g1 = annotated.get(gene1);
            for (int j = i + 1; j < yeastGenes.size(); j++) {
                YeastGene gene2 = yeastGenes.get(j);
                Gene g2 = annotated.get(gene2);
                String symbols[] = {gene1.getSymbol(), gene2.getSymbol()};
                Arrays.sort(symbols);
                String key = symbols[0] + ":" + symbols[1];
                if (!keys.contains(key)) {

                    SemanticSimilarity ss = new SemanticSimilarity(g1, g2);
                    if (sfp.getSimilarityHash().containsKey(ss.hashCode())) {
                        int sim = ((SemanticSimilarity) sfp.getSimilarityHash().get(ss.hashCode())).getSimilarity();
                        if (sim >= ssCutoff) {
                            count++;
                        }
                    } else if (ssCutoff == 0) {
                        count++;
                    }
                    total++;

                    keys.add(key);
                } else {
//                    System.out.println("again, key: "+key);
                }


            }
        }

        ProportionStat stat = new ProportionStat(count, total);
        return stat;
    }

    private class ProportionStat {

        int count;
        int total;

        public ProportionStat(int count, int total) {
            this.count = count;
            this.total = total;
        }

        public double getProp() {
            return (count + 0.0) / total;
        }

        public int getCount() {
            return count;
        }

        public int getTotal() {
            return total;
        }
    }
}
